<?php

/*
	Question2Answer (c) Gideon Greenspan

	http://www.question2answer.org/

	
	File: qa-include/qa-page-question.php
	Version: See define()s at top of qa-include/qa-base.php
	Description: Controller for question page (only viewing functionality here)


	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	More about this license: http://www.question2answer.org/license.php
*/

if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
    header('Location: ../');
    exit;
}

require_once QA_INCLUDE_DIR . 'qa-app-cookies.php';
require_once QA_INCLUDE_DIR . 'qa-app-format.php';
require_once QA_INCLUDE_DIR . 'qa-db-selects.php';
require_once QA_INCLUDE_DIR . 'qa-util-sort.php';
require_once QA_INCLUDE_DIR . 'qa-util-string.php';
require_once QA_INCLUDE_DIR . 'qa-app-captcha.php';
require_once QA_INCLUDE_DIR . 'qa-page-question-view.php';
require_once QA_INCLUDE_DIR . 'qa-app-updates.php';

$questionid = qa_request_part(0);
$userid = qa_get_logged_in_userid();
$cookieid = qa_cookie_get();


//	Get information about this question

list($question, $childposts, $achildposts, $parentquestion, $closepost, $extravalue, $categories, $favorite) = qa_db_select_with_pending(
    qa_db_full_post_selectspec($userid, $questionid),
    qa_db_full_child_posts_selectspec($userid, $questionid),
    qa_db_full_a_child_posts_selectspec($userid, $questionid),
    qa_db_post_parent_q_selectspec($questionid),
    qa_db_post_close_post_selectspec($questionid),
    qa_db_post_meta_selectspec($questionid, 'qa_q_extra'),
    qa_db_category_nav_selectspec($questionid, true, true, true),
    isset($userid) ? qa_db_is_favorite_selectspec($userid, QA_ENTITY_QUESTION, $questionid) : null
);

if ($question['basetype'] != 'Q') // don't allow direct viewing of other types of post
    $question = null;

if (isset($question)) {
    $question['extra'] = $extravalue;

    $answers = qa_page_q_load_as($question, $childposts);
    $commentsfollows = qa_page_q_load_c_follows($question, $childposts, $achildposts);

    $question = $question + qa_page_q_post_rules($question, null, null, $childposts); // array union

    if ($question['selchildid'] && (@$answers[$question['selchildid']]['type'] != 'A'))
        $question['selchildid'] = null; // if selected answer is hidden or somehow not there, consider it not selected

    foreach ($answers as $key => $answer) {
        $answers[$key] = $answer + qa_page_q_post_rules($answer, $question, $answers, $achildposts);
        $answers[$key]['isselected'] = ($answer['postid'] == $question['selchildid']);
    }

    foreach ($commentsfollows as $key => $commentfollow) {
        $parent = ($commentfollow['parentid'] == $questionid) ? $question : @$answers[$commentfollow['parentid']];
        $commentsfollows[$key] = $commentfollow + qa_page_q_post_rules($commentfollow, $parent, $commentsfollows, null);
    }
}

//	Deal with question not found or not viewable, otherwise report the view event

if (!isset($question))
    return include QA_INCLUDE_DIR . 'qa-page-not-found.php';

if (!$question['viewable']) {
    $qa_content = qa_content_prepare();

    if ($question['queued'])
        $qa_content['error'] = qa_lang_html('question/q_waiting_approval');
    elseif ($question['flagcount'] && !isset($question['lastuserid']))
        $qa_content['error'] = qa_lang_html('question/q_hidden_flagged'); elseif ($question['authorlast'])
        $qa_content['error'] = qa_lang_html('question/q_hidden_author'); else
        $qa_content['error'] = qa_lang_html('question/q_hidden_other');

    $qa_content['suggest_next'] = qa_html_suggest_qs_tags(qa_using_tags());

    return $qa_content;
}

$permiterror = qa_user_post_permit_error('permit_view_q_page', $question, null, false);

if ($permiterror && (qa_is_human_probably() || !qa_opt('allow_view_q_bots'))) {
    $qa_content = qa_content_prepare();
    $topage = qa_q_request($questionid, $question['title']);

    switch ($permiterror) {
        case 'login':
            $qa_content['error'] = qa_insert_login_links(qa_lang_html('main/view_q_must_login'), $topage);
            break;

        case 'confirm':
            $qa_content['error'] = qa_insert_login_links(qa_lang_html('main/view_q_must_confirm'), $topage);
            break;

        case 'approve':
            $qa_content['error'] = qa_lang_html('main/view_q_must_be_approved');
            break;

        default:
            $qa_content['error'] = qa_lang_html('users/no_permission');
            break;
    }

    return $qa_content;
}


//	Determine if captchas will be required

$captchareason = qa_user_captcha_reason(qa_user_level_for_post($question));
$usecaptcha = ($captchareason != false);


//	If we're responding to an HTTP POST, include file that handles all posting/editing/etc... logic
//	This is in a separate file because it's a *lot* of logic, and will slow down ordinary page views

$pagestart = qa_get_start();
$pagestate = qa_get_state();
$showid = qa_get('show');
$pageerror = null;
$formtype = null;
$formpostid = null;
$jumptoanchor = null;
$commentsall = null;

if (substr($pagestate, 0, 13) == 'showcomments-') {
    $commentsall = substr($pagestate, 13);
    $pagestate = null;

} elseif (isset($showid)) {
    foreach ($commentsfollows as $comment)
        if ($comment['postid'] == $showid) {
            $commentsall = $comment['parentid'];
            break;
        }
}

if (qa_is_http_post() || strlen($pagestate))
    require QA_INCLUDE_DIR . 'qa-page-question-post.php';

$formrequested = isset($formtype);

if ((!$formrequested) && $question['answerbutton']) {
    $immedoption = qa_opt('show_a_form_immediate');

    if (($immedoption == 'always') || (($immedoption == 'if_no_as') && (!$question['isbyuser']) && (!$question['acount'])))
        $formtype = 'a_add'; // show answer form by default
}


//	Get information on the users referenced

$usershtml = qa_userids_handles_html(array_merge(array($question), $answers, $commentsfollows), true);


//	Prepare content for theme

$qa_content = qa_content_prepare(true, array_keys(qa_category_path($categories, $question['categoryid'])));

if (isset($userid) && !$formrequested)
    $qa_content['favorite'] = qa_favorite_form(QA_ENTITY_QUESTION, $questionid, $favorite,
        qa_lang($favorite ? 'question/remove_q_favorites' : 'question/add_q_favorites'));

$qa_content['script_rel'][] = 'qa-content/qa-question.js?' . QA_VERSION;

if (isset($pageerror))
    $qa_content['error'] = $pageerror; // might also show voting error set in qa-index.php

elseif ($question['queued'])
    $qa_content['error'] = $question['isbyuser'] ? qa_lang_html('question/q_your_waiting_approval') : qa_lang_html('question/q_waiting_your_approval');

if ($question['hidden'])
    $qa_content['hidden'] = true;

qa_sort_by($commentsfollows, 'created');


//	Prepare content for the question...

if ($formtype == 'q_edit') { // ...in edit mode
    $qa_content['title'] = qa_lang_html($question['editable'] ? 'question/edit_q_title' :
        (qa_using_categories() ? 'question/recat_q_title' : 'question/retag_q_title'));
    $qa_content['form_q_edit'] = qa_page_q_edit_q_form($qa_content, $question, @$qin, @$qerrors, $completetags, $categories);
    $qa_content['q_view']['raw'] = $question;

} else { // ...in view mode
    $qa_content['q_view'] = qa_page_q_question_view($question, $parentquestion, $closepost, $usershtml, $formrequested);

    $qa_content['title'] = $qa_content['q_view']['title'];

    $qa_content['description'] = qa_html(qa_shorten_string_line(qa_viewer_text($question['content'], $question['format']), 150));

    $categorykeyword = @$categories[$question['categoryid']]['title'];

    $qa_content['keywords'] = qa_html(implode(',', array_merge(
        (qa_using_categories() && strlen($categorykeyword)) ? array($categorykeyword) : array(),
        qa_tagstring_to_tags($question['tags'])
    ))); // as far as I know, META keywords have zero effect on search rankings or listings, but many people have asked for this
}


//	Prepare content for an answer being edited (if any) or to be added

if ($formtype == 'a_edit') {
    $qa_content['a_form'] = qa_page_q_edit_a_form($qa_content, 'a' . $formpostid, $answers[$formpostid],
        $question, $answers, $commentsfollows, @$aeditin[$formpostid], @$aediterrors[$formpostid]);

    $qa_content['a_form']['c_list'] = qa_page_q_comment_follow_list($question, $answers[$formpostid],
        $commentsfollows, true, $usershtml, $formrequested, $formpostid);

    $jumptoanchor = 'a' . $formpostid;

} elseif (($formtype == 'a_add') || ($question['answerbutton'] && !$formrequested)) {
    $qa_content['a_form'] = qa_page_q_add_a_form($qa_content, 'anew', $captchareason, $question, @$anewin, @$anewerrors, $formtype == 'a_add', $formrequested);

    if ($formrequested)
        $jumptoanchor = 'anew';
    elseif ($formtype == 'a_add')
        $qa_content['script_onloads'][] = array(
            "qa_element_revealed=document.getElementById('anew');"
        );
}


//	Prepare content for comments on the question, plus add or edit comment forms

if ($formtype == 'q_close') {
    $qa_content['q_view']['c_form'] = qa_page_q_close_q_form($qa_content, $question, 'close', @$closein, @$closeerrors);
    $jumptoanchor = 'close';

} elseif ((($formtype == 'c_add') && ($formpostid == $questionid)) || ($question['commentbutton'] && !$formrequested)) { // ...to be added
    $qa_content['q_view']['c_form'] = qa_page_q_add_c_form($qa_content, $question, $question, 'c' . $questionid,
        $captchareason, @$cnewin[$questionid], @$cnewerrors[$questionid], $formtype == 'c_add');

    if (($formtype == 'c_add') && ($formpostid == $questionid)) {
        $jumptoanchor = 'c' . $questionid;
        $commentsall = $questionid;
    }

} elseif (($formtype == 'c_edit') && (@$commentsfollows[$formpostid]['parentid'] == $questionid)) { // ...being edited
    $qa_content['q_view']['c_form'] = qa_page_q_edit_c_form($qa_content, 'c' . $formpostid, $commentsfollows[$formpostid],
        @$ceditin[$formpostid], @$cediterrors[$formpostid]);

    $jumptoanchor = 'c' . $formpostid;
    $commentsall = $questionid;
}

$qa_content['q_view']['c_list'] = qa_page_q_comment_follow_list($question, $question, $commentsfollows,
    $commentsall == $questionid, $usershtml, $formrequested, $formpostid); // ...for viewing


//	Prepare content for existing answers (could be added to by Ajax)

$qa_content['a_list'] = array(
    'tags' => 'id="a_list"',
    'as' => array(),
);

// sort according to the site preferences

if (qa_opt('sort_answers_by') == 'votes') {
    foreach ($answers as $answerid => $answer)
        $answers[$answerid]['sortvotes'] = $answer['downvotes'] - $answer['upvotes'];

    qa_sort_by($answers, 'sortvotes', 'created');

} else
    qa_sort_by($answers, 'created');

// further changes to ordering to deal with queued, hidden and selected answers

$countfortitle = $question['acount'];
$nextposition = 10000;
$answerposition = array();

foreach ($answers as $answerid => $answer)
    if ($answer['viewable']) {
        $position = $nextposition++;

        if ($answer['hidden'])
            $position += 10000;

        elseif ($answer['queued']) {
            $position -= 10000;
            $countfortitle++; // include these in displayed count

        } elseif ($answer['isselected'] && qa_opt('show_selected_first'))
            $position -= 5000;

        $answerposition[$answerid] = $position;
    }

asort($answerposition, SORT_NUMERIC);

// extract IDs and prepare for pagination

$answerids = array_keys($answerposition);
$countforpages = count($answerids);
$pagesize = qa_opt('page_size_q_as');

// see if we need to display a particular answer

if (isset($showid)) {
    if (isset($commentsfollows[$showid]))
        $showid = $commentsfollows[$showid]['parentid'];

    $position = array_search($showid, $answerids);

    if (is_numeric($position))
        $pagestart = floor($position / $pagesize) * $pagesize;
}

// set the canonical url based on possible pagination

$qa_content['canonical'] = qa_path_html(qa_q_request($question['postid'], $question['title']),
    ($pagestart > 0) ? array('start' => $pagestart) : null, qa_opt('site_url'));

// build the actual answer list

$answerids = array_slice($answerids, $pagestart, $pagesize);

foreach ($answerids as $answerid) {
    $answer = $answers[$answerid];

    if (!(($formtype == 'a_edit') && ($formpostid == $answerid))) {
        $a_view = qa_page_q_answer_view($question, $answer, $answer['isselected'], $usershtml, $formrequested);

        //	Prepare content for comments on this answer, plus add or edit comment forms

        if ((($formtype == 'c_add') && ($formpostid == $answerid)) || ($answer['commentbutton'] && !$formrequested)) { // ...to be added
            $a_view['c_form'] = qa_page_q_add_c_form($qa_content, $question, $answer, 'c' . $answerid,
                $captchareason, @$cnewin[$answerid], @$cnewerrors[$answerid], $formtype == 'c_add');

            if (($formtype == 'c_add') && ($formpostid == $answerid)) {
                $jumptoanchor = 'c' . $answerid;
                $commentsall = $answerid;
            }

        } else if (($formtype == 'c_edit') && (@$commentsfollows[$formpostid]['parentid'] == $answerid)) { // ...being edited
            $a_view['c_form'] = qa_page_q_edit_c_form($qa_content, 'c' . $formpostid, $commentsfollows[$formpostid],
                @$ceditin[$formpostid], @$cediterrors[$formpostid]);

            $jumptoanchor = 'c' . $formpostid;
            $commentsall = $answerid;
        }

        $a_view['c_list'] = qa_page_q_comment_follow_list($question, $answer, $commentsfollows,
            $commentsall == $answerid, $usershtml, $formrequested, $formpostid); // ...for viewing

        //	Add the answer to the list

        $qa_content['a_list']['as'][] = $a_view;
    }
}

if ($question['basetype'] == 'Q') {
    $qa_content['a_list']['title_tags'] = 'id="a_list_title"';

    if ($countfortitle == 1)
        $qa_content['a_list']['title'] = qa_lang_html('question/1_answer_title');
    elseif ($countfortitle > 0)
        $qa_content['a_list']['title'] = qa_lang_html_sub('question/x_answers_title', $countfortitle); else
        $qa_content['a_list']['title_tags'] .= ' style="display:none;" ';
}

if (!$formrequested)
    $qa_content['page_links'] = qa_html_page_links(qa_request(), $pagestart, $pagesize, $countforpages, qa_opt('pages_prev_next'), array(), false, 'a_list_title');


//	Some generally useful stuff

if (qa_using_categories() && count($categories))
    $qa_content['navigation']['cat'] = qa_category_navigation($categories, $question['categoryid']);

if (isset($jumptoanchor))
    $qa_content['script_onloads'][] = array(
        'qa_scroll_page_to($("#"+' . qa_js($jumptoanchor) . ').offset().top);'
    );


//	Determine whether this request should be counted for page view statistics

if (
    qa_opt('do_count_q_views') &&
    (!$formrequested) &&
    (!qa_is_http_post()) &&
    qa_is_human_probably() &&
    ((!$question['views']) || ( // if it has more than zero views
        (($question['lastviewip'] != qa_remote_ip_address()) || (!isset($question['lastviewip']))) && // then it must be different IP from last view
        (($question['createip'] != qa_remote_ip_address()) || (!isset($question['createip']))) && // and different IP from the creator
        (($question['userid'] != $userid) || (!isset($question['userid']))) && // and different user from the creator
        (($question['cookieid'] != $cookieid) || (!isset($question['cookieid']))) // and different cookieid from the creator
    ))
)
    $qa_content['inc_views_postid'] = $questionid;


return $qa_content;


/*
	Omit PHP closing tag to help avoid accidental output
*/